//
//  TWFXNSConnection.m
//  TWFXWeather
//
//  Created by Lion User on 13-9-30.
//  Copyright (c) 2013年 Lion User. All rights reserved.
//

#import "TWFXNSConnection.h"
#import <sys/socket.h>

#import <netinet/in.h>

#import <arpa/inet.h>

#import <netdb.h>

NSString* URLOfCurrentCon;

@implementation TWFXNSConnection

-(id) init
{
    if (self = [super init]) {
        
        self.resultObj = [[[NSMutableData alloc] init] autorelease];
        self.flag_requestTime = 0;
    }
    
    return self;
}


-(void) DownLoadByURL:(NSURL *)url
{

   // NSString *strURL = @"http://m.weather.com.cn/data/101180601.html";
    
    //根据URL创建 NSURLRequest 请求.timeoutInterval参数表示超时的的时间,单位是秒
    NSURLRequest *request = [[NSURLRequest alloc]
                             initWithURL:url
                             cachePolicy:NSURLRequestUseProtocolCachePolicy
                             timeoutInterval:10];

    //参数cachePolicy表示缓存策略,枚举类型,值有以下几种：
    //
    //    enum
    //    {
    //        NSURLRequestUseProtocolCachePolicy  = 0  NSURLRequest默认的cache policy，使用Protocol协议定义。是最能保持一致性的协议。
    //        NSURLRequestReloadIgnoringCacheData = 1  忽略缓存直接从原始地址下载 = NSURLRequestReloadIgnoringCacheData
    //        NSURLRequestReturnCacheDataElseLoad = 2  只有在cache中不存在data时才从原始地址下载
    //        NSURLRequestReturnCacheDataDontLoad = 3  只使用cache数据，如果不存在cache，请求失败;用于没有建立网络连接离线模式;
    //        NSURLRequestReloadIgnoringLocalAndRemoteCacheData =4,  忽略本地和远程的缓存数据，直接从原始地址下载，与NSURLRequestReloadIgnoringCacheData类似。
    //        NSURLRequestReloadRevalidatingCacheData = 5  验证本地数据与远程数据是否相同，如果不同则下载远程数据，否则使用本地数据。
    //    };
    //    typedef NSUInteger NSURLRequestCachePolicy;
    
    
    //创建连接,该消息一发送下载会立即开始,异步(我猜是异步)触发 didReceiveResponse 方法 表示真的开始了.
    
    //如果有多个下载请求的话,系统会对它们进行排队(在 didReceiveResponse 方法前排队),第一个下载请求下载完成执行完 connectionDidFinishLoading 方法 和回调函数(如果有)之后,才开始第二个下载请求(调用它的 didReceiveResponse 方法)
    
    //所以不要在这个方法里的设置self的属性,因为前一个下载请求的设置就会被后一个下载请求的设置覆盖掉.如果想设置某些属于某一个下载请求的信息,请放在didReceiveResponse方法里
    
    //在代理(得了噶个)收到connectionDidFinishLoading：或者didFailWithError：消息之前 可以通过给连接发送一个cancel：消息来中断下载
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    
     [request release];
    
    if (!connection)
    {
        NSLog(@"创建网络连接失败!");
    }

}



//当服务器提供了足够客户程序创建NSURLResponse对象的信息时，代理对象会收到
//一个connection：didReceiveResponse：消息，在消息内可以检查NSURLResponse
//对象和确定数据的预期长度，mime类型，文件名以及其他服务器提供的元信息

//要注意，一个简单的连接也可能会收到多个connection：didReceiveResponse：消息
//当服务器连接重置或者一些罕见的原因（比如多组mime文档），代理都会收到该消息
//这时候应该重置进度指示，丢弃之前接收的数据

//反正当收到该信息就表示下载开始了(或者是重新开始了),把之前的数据清空即可

//多个下载请求时,前一个下载完执行完回调函数之后,才会开始执行下一个下载请求的 didReceiveResponse 方法

//一些仅属于某个下载请求的类的实例属性,应该放在这里设置
-(void)connection:connection didReceiveResponse:(NSURLResponse *)response
{
 
    URLOfCurrentCon = response.URL.absoluteString;
    [self.resultObj setLength:0];
    
    //int expectedLength = [response expectedContentLength];  该方法可以获取将要下载的信息的大小(字节长度)
}


//当下载开始的时候，每当有数据接收，代理会定期收到connection：didReceiveData：消息
//代理应当在实现中储存新接收的数据，下面的例子既是如此
//在下面的方法实现中，可以加入一个进度指示器，提示用户下载进度
-(void)connection:connection didReceiveData:(NSData *)data
{
   // NSLog(@"test %@",self.strTest);

    
    [self.resultObj appendData:data];
    
    // [data length]; 表示每次接收的信息的大小(字节长度)
}


//当下载的过程中有错误发生的时候，代理会收到一个connection：didFailWithError消息
//消息参数里面的NSError对象提供了具体的错误细节，它也能提供在用户信息字典里面失败的
//url请求（使用NSErrorFailingURLStringKey）

//当代理接收到连接的connection：didFailWithError消息后，该连接不会再收到任何消息,所以应该release掉

-(void)connection:connection didFailWithError:(NSError *)error
{
    [connection release];

    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
    
    self.flag_requestTime ++;
    
    [self.delegateOfCon downloadIsFail:error URL:URLOfCurrentCon];
}


//最后，如果连接请求成功的下载，代理会接收connectionDidFinishLoading：消息
//该消息之后代理不会再收到其他任何的消息了，在消息的实现中，应该释放掉连接

//如果有多次请求连接下载,每次成功下载完成都会调用这个方法
//如果有几个下载请求在同时进行,当其中某一个请求(比如A请求)率先完成下载而正在执行didFinish方法时,
//如果此时也有其他的下载请求(比如B请求)下载完成了,要等上一个请求(A请求)正在执行的didFinish方法执行完之后,
//才执行B请求的difinish方法

//疑问:但是几个请求都是使用同一个类实例的 resultObj属性啊,为什么不会混淆?为什么其他属性会被覆盖?
- (void)connectionDidFinishLoading: (NSURLConnection *) connection
{
    //do something with the data
    
    NSString *strOfURL = [NSString stringWithFormat:@"%@",connection.currentRequest.URL.absoluteString];
    
    [connection release];

    self.flag_requestTime ++;
    
    [self.delegateOfCon DownloadIsSucceed:self.resultObj strOfURL:strOfURL];

}


+(BOOL)isNetworkReachable
{
    // Create zero addy
    
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;
    
    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;
    
    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);
    
    if (!didRetrieveFlags)
    {
        return NO;
    }
    
    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    return (isReachable && !needsConnection) ? YES : NO;

}



-(void)dealloc
{
    self.resultObj = nil;
    [super dealloc];
}


@end
